// Initial File - Paul Jack


// QT Includes
#include <qtcore>
#include <qapplication.h>
#include <qdatetime.h>
#include <qlist.h>
#include <qtimer.h>

// Windows includes
//#include <windows.h>
//#include <winioctl.h>


#include "usbasyncmgr.h"
#include "usbconstants.h"

/// The maximum size of each transfer that we will perform. (both in and
/// out). We will not write any command larger than this, but we can receive
/// responses over multiple packets larger than this.
#define R_USB_MAX_TRANSFER 2048




    


/*!
 * UsbAsyncMgr::UsbAsyncMgr 
 *
 * Description: 
 *
 * @param name is of type QString 
 * @param deviceId is of type QString 
 *
 * @returns None
 */
UsbAsyncMgr::UsbAsyncMgr(QString name, QString deviceId, quint32 bufferSize) :
AsyncMgrBase(name, QString("NONE"), deviceId, bufferSize)
{

    mBuffer.resize(R_USB_MAX_TRANSFER + 1);

    // Make a connection to my device.
    // This only works if the device is not currently connected for detecting the device
    // the first time.
    QObject::connect(Usb::getInstance(), SIGNAL(deviceListChanged(bool,QList<UsbDevice *>)), this, SLOT(checkForConnection(bool,QList<UsbDevice *>)));

    // Here we will directly attach to the device if it is already attached since we won't
    // get a connect message since it's already happened!
    bool found = false;

    // This is the magic to the code.  Without this we would not be able
    // to replace the device type.  However, doing it this way allows us to 
    // use our AsyncMgr with any type of device as long as it
    // is derived from the CommDevice
    QList < UsbDevice *> devList = Usb::getInstance()->getDeviceList();

    // Now that we have the "attached" device list, we need to iterate through it
    // To see if one of the devices attached matches our serial number.
    // If it does then we will connect to it.
    // If we are already connected to it then we don't do anything as this notification
    // probably happened because there's multiple devices attached to the USB driver.
    int devIndex;
    for( devIndex = 0; devIndex < devList.count(); devIndex++ )
    {
        
        qDebug("Search for mIdentification: %s Found: %s",  mIdentification.toLocal8Bit().constData(), devList[devIndex]->getIdentification().toLocal8Bit().constData());
        QString identification = devList[devIndex]->getIdentification();
        //identification.sprintf("%s", devList[devIndex]->getIdentification().trimmed());

        
        if( identification == mIdentification )
        {
            found = true;
            break;
        }
    }


    if(found)
    {
        // At this point we have 
        //    - found our serial number in the list
        //    - figured out this is an attach message
        //    - realized we are not already attached
        // So, let's connect to the device!

        mDevice = devList[devIndex];

        mDevice->isConnected();
        WDU_DEVICE *pWduDevice;

        UINT32 error = WDU_GetDeviceInfo(mDevice->mhDevice, &pWduDevice);
         
        if(error != 0)
        {
            qDebug("AsyncMgr::AsyncMgr: WDU_GetDeviceInfo() failed: error 0x%lx "
                   "(\"%s\")", error, Stat2Str(error));
        }

        qDebug() << "Attached to device: " << mIdentification;
        start();
    
        mAttached = true;
        emit connectionStatus( mAttached );

    }






}






/*!
 * UsbAsyncMgr::checkForConnection 
 *
 * Description: 
 * This method responds to a deviceListChanged signal.
 * @param attached is of type bool 
 * @param *> deviceList is of type QList<UsbDevice 
 *
 * @returns void 
 */
void UsbAsyncMgr::checkForConnection(bool attached, QList<UsbDevice *> deviceList)
{

    // Begin by searching the list and looking for our serial number
    // If we are not in the list then this connection does not belong 
    // to us.

    bool found = false;

    // This is the magic to the code.  Without this we would not be able
    // to replace the device type.  However, doing it this way allows us to 
    // use our AsyncMgr with any type of device as long as it
    // is derived from the CommDevice
    QList < UsbDevice *> devList = Usb::getInstance()->getDeviceList();

    // Now that we have the "attached" device list, we need to iterate through it
    // To see if one of the devices attached matches our serial number.
    // If it does then we will connect to it.
    // If we are already connected to it then we don't do anything as this notification
    // probably happened because there's multiple devices attached to the USB driver.
    int devIndex;
    for( devIndex = 0; devIndex < devList.count(); devIndex++ )
    {
        
        qDebug("Search for mIdentification: %s Found: %s",  mIdentification.toLocal8Bit().constData(), devList[devIndex]->getIdentification().toLocal8Bit().constData());
        QString identification = devList[devIndex]->getIdentification();
        //identification.sprintf("%s", devList[devIndex]->getIdentification().trimmed());

        
        if( identification == mIdentification )
        {
            found = true;
            break;
        }
    }


    // If we are in the list then we need to figure out if we are attaching or detaching.
    if( found )
    {
        // Is this an attach message?
        if( attached )
        {
            // Are we already attached?
            if( !mAttached )
            {

                // At this point we have 
                //    - found our serial number in the list
                //    - figured out this is an attach message
                //    - realized we are not already attached
                // So, let's connect to the device!

                mDevice = devList[devIndex];

                mDevice->isConnected();
                WDU_DEVICE *pWduDevice;

                UINT32 error = WDU_GetDeviceInfo(mDevice->mhDevice, &pWduDevice);
                     
                if(error != 0)
                {
                    qDebug("AsyncMgr::AsyncMgr: WDU_GetDeviceInfo() failed: error 0x%lx "
                           "(\"%s\")", error, Stat2Str(error));
                }

                qDebug() << "Attached to device: " << mIdentification;
                start();
                
                mAttached = true;
                emit connectionStatus( mAttached );

            }
        }
    }
    else
    {
        // We are not in the list

        if( !attached )
        {
            // This is a disconnect message

            if( mAttached )
            {
                // At this point we have found out that our serial number is not in the list!
                // And we have figured out this is a detach message
                // And that we were attached before.
                // So, lets disconnect from the device!
                

                // Stop
                // Assign Null device
                // Good to go!
                stop();
                mDevice = &mNullDevice;
                mAttached = false;
                qDebug("Detached from device: %d", mIdentification.toInt());
                emit connectionStatus( mAttached );
            }
        }
    }
}





